;%define   com             ;注释用于MBR，不注释用于COM调试
%ifdef    com
orgaddr   equ   100h       ;用于COM调试的设置
%else
orgaddr   equ   7c00h      ;用于MBR启动的设置
%endif

VESA equ 0

jmp start

start:
mov ax, cs
add ax, orgaddr/10h
mov ds, ax
mov es, ax


call  setmode
call  getdisplayaddr
call  drawimg2


%ifdef    com           ;如果是.COM调试，需要调用DOS返回中断
mov ah,4ch
int 21h
%endif                  ;.COM程序将在此顺利返回Dos系统

jmp $                   ;如果是MBR启动，将在此停止运行

setmode:
mov AX,4F02H
mov bx,4101H        ;640*480  256色   第1个值4表示为要使用线性地址模式
int 10h


;取得该模式下显存线性地址,调用0x4F01 功能号，获得信息
getdisplayaddr:
mov ax,0x9000    ;指定一个放置显存线性地址的地方
mov es,ax
mov di,  VESA

mov ax , 0x4f01
mov cx , 0x101
int 0x10
;返回的结构体中偏移量为40 的地方，即es:di+40 处，用4字节存放了一个线性地址，
;这就是这个显卡在此模式下显存的线性地址

;dw  0x1234 --- 0x34 0x12  注意DWORD的内存放置顺序，低地址为低位，高地址为高位
mov bx,[ es:VESA+40 ]    ;0000 取出线性显存的低16位地址
mov dx,[ es:VESA+42 ]    ;C000 取出线性显存的高16位地址
ret


;向取得的显存地址里写数据直接绘制图形
drawimg2:
;mov  ax,0xa000         ;这里用0xa000是测试图像显示，说明显示子程序没有问题
;mov  es,ax             ;但真正这里需要的是用dx和bx组合的32位线性显存地址来绘图
mov cx,0xffff
mov bl,3
mov si,0
nextpoint2:
mov  [es:si],bl   ;调色板颜色索引送往显存地址
inc si
loop  nextpoint2
ret

times 510-($-$$) db 0
      db 0x55,0xaa